﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SLAU;

namespace Solvers
{
    public class ZeidelNonStatic : Solver
    {
        public ZeidelNonStatic(SLAU.SLAU system, double precision)
            : base(system, precision)
        {
            this.StartVector = system.StartVector;
            this.System.Normalize();
        }

        public Vector StartVector { get; set; }

        public override void Solve()
        {
            if (!this.System.CheckConvergence())
            {
                return;
            }

            int n = this.System.EquationsCount;
            Vector free = this.System.Free;
            Matrix coeff = this.System.Coefficients;

            Vector tmp = new Vector(n);
            Vector tmp2 = new Vector(n);

            Vector for_smth = new Vector(n);

            Vector stor = new Vector(free);

            double ok;
            do
            {
                tmp.CopyTo(tmp2);

                for (int i = 0; i < n; i++)
                {
                    tmp[i] = 0;
                    for (int j = 0; j < n; j++)
                    {
                        tmp[i] += coeff[i, j] * stor[j];
                    }
                    tmp[i] += free[i];
                    stor[i] = tmp[i];
                }

                delta(tmp, tmp2).CopyTo(for_smth);

                ok = Math.Abs(this.StartVector[0] - for_smth[0]);

                for (int i = 0; i < n; i++)
                {
                    if (Math.Abs(this.StartVector[i] - for_smth[i]) > ok)
                    {
                        ok = Math.Abs(this.StartVector[i] - for_smth[i]);
                    }
                    this.StartVector[i] = for_smth[i];
                }
            } while (ok > this.Precision);

            this.Solution = new Vector(tmp);
            this.Solved = true;
        }

        private Vector delta(Vector v1, Vector v2)
        {
            double[] mas = new double[v1.Length];

            for (int i = 0; i < v1.Length; i++)
            {
                mas[i] = Math.Abs(v1[i] - v2[i]);
            }

            Array.Sort(mas);
            mas = mas.Reverse().ToArray();
            return new Vector(mas);
        }
    }
}
